package main

import (
	"os"
	"crypto/md5"
	"io"
	"flag"
	"fmt"
	"encoding/json"
	"aws_sys_monitor/common"
	"github.com/aws/aws-sdk-go/service/cloudwatch"
	"github.com/aws/aws-sdk-go/aws"
)

const jsonFile = "/usr/share/.file_md5.json"

var criticalFile = []string{
	"/etc/passwd",
	"/etc/shadow",
	"/etc/group",
	"/etc/gshadow",
}

var (
	Isupdate = flag.Bool("update", false, "重新生成MD5校验")
)

type FileMd5 struct {
	Md5Values map[string]string `value:{"/etc/passwd":"jgojerg2344t34gkmh3h"}`
}

func main() {
	flag.Parse()
	if *Isupdate {
		md5update()
	} else {
		md5verify()
	}

}

func md5update() {
	newMd5 := &FileMd5{make(map[string]string)}

	for _, path := range criticalFile {
		md5Value, err := fileMd5(path)
		if err != nil {
			fmt.Printf("无法找到该文件 %s\n", err)
			break
		}
		newMd5.Md5Values[path] = md5Value
	}
	newMd5.JsonDumpTofile()
}

func md5verify()  {
	oldMd5 := &FileMd5{make(map[string]string)}
	oldMd5.JsonLoad()
	oldMd5value := oldMd5.Md5Values
	ok := true

	for _, path := range criticalFile {
		md5Value, err := fileMd5(path)
		if err != nil {
			fmt.Printf("无法找到该文件 %s\n", err)
			break
		}
		if oldMd5value[path] !=  md5Value {
			fmt.Printf("%s 文件内容被修改\n",path)
			ok = false
			break
		}
	}
	if ok {
		var isVertify float64 = 0
		sendAlarmdata(isVertify)
	} else {
		var isVertify float64 = 1
		sendAlarmdata(isVertify)
	}
	fmt.Printf("执行结果 %v\n",ok)


}

func sendAlarmdata(isVertify float64)  {
	instanceId, _ := common.HttpGet()

	md5IsVerifyData := &cloudwatch.MetricDatum{
		MetricName: aws.String("FileMd5Verify"),
		Unit:       aws.String("None"),
		Value:      aws.Float64(isVertify),
		Dimensions: []*cloudwatch.Dimension{{Name: aws.String("InstanceId"), Value: aws.String(instanceId)},
		},
	}
	common.MetricDataPut(md5IsVerifyData,"System/Linux")

}



func fileMd5(filePath string) (md5Value string, err error) {
	file, err := os.Open(filePath)

	defer file.Close()
	if err == nil {
		md5h := md5.New()
		io.Copy(md5h, file)
		md5Value = fmt.Sprintf("%x", md5h.Sum(nil))

	}
	return
}

func (filemd5 *FileMd5) JsonDumpTofile() (err error) {
	js, _ := json.Marshal(filemd5)
	fmt.Printf("JSON format: %s\n", js)
	// using an encoder:
	file, err := os.OpenFile(jsonFile, os.O_CREATE|os.O_WRONLY, 0600)
	if err != nil {
		fmt.Printf("can not open the file %s", err)
	}
	defer file.Close()
	enc := json.NewEncoder(file)
	err = enc.Encode(filemd5)
	if err != nil {
		fmt.Printf("Error in encoding json %s", err)
	}
	return
}

func (filemd5 *FileMd5) JsonLoad() (err error) {
	file, err := os.Open(jsonFile)
	enc := json.NewDecoder(file)
	err = enc.Decode(filemd5)
	fmt.Println(filemd5)
	return

}
